//
//  XWHAOFFittingWDRCGainLineChartView.swift
//  XWHAOfflineFitting
//
//  Created by edy on 2024/3/6.
//

import UIKit
import Charts

class XWHAOFFittingWDRCGainLineChartView: AppLineChartView {

    private(set) lazy var iconView = UIImageView()
    
    private(set) lazy var freqBandList: [Int] = []
    
    var volumeUnitText: String {
        "dB SPL"
    }
    
    var realMPODateSetLabel: String {
        "RealMPO"
    }
    var maxMPODateSetLabel: String {
        "MaxMPO"
    }
    
    var dashedLowDateSetLabel: String {
        "DashedLow"
    }
    var dashedMidDateSetLabel: String {
        "DashedMid"
    }
    var dashedHighDateSetLabel: String {
        "DashedHigh"
    }
    
    var solidLowDateSetLabel: String {
        "SolidLow"
    }
    var solidMidDateSetLabel: String {
        "SolidMid"
    }
    var solidHighDateSetLabel: String {
        "SolidHigh"
    }
    
    var deviceType = XWDeviceModelType.none
    var isLeft: Bool = true
    
    override func addSubViews() {
        super.addSubViews()
        
        addSubview(iconView)
        
        layer.cornerRadius = 16
        layer.backgroundColor = collectionBgColor.cgColor
    }
    
    override func relayoutSubViews() {
        iconView.snp.makeConstraints { make in
            make.left.equalToSuperview()
            make.width.equalTo(67)
            make.top.equalToSuperview()
            make.height.equalTo(24)
        }
        chartView.snp.makeConstraints { make in
            make.left.right.equalToSuperview()
            make.top.equalTo(iconView.snp.bottom).offset(4)
            make.bottom.equalToSuperview().inset(8)
        }
    }
    
    func updateChart(deviceType: XWDeviceModelType, deviceVersion: String, isLeft: Bool, wdrcContainerModel: XWHAOFWDRCContainerModel, operationModel: XWHAOFWDRCGainChartOperationModel, sheetOperationModel: XWHAOFWDRCGainSheetOperationModel) {
        self.deviceType = deviceType
        self.isLeft = isLeft
        
        freqBandList = WDRCModule.getWDRCMustFreqBandList(deviceType: deviceType, deviceVersion: deviceVersion)
        configXAxis()
        
        var lineColor: UIColor
        var markerBg: UIImage?
        
        var chartTipIconName: String = ""
        
        var dashedLowItems: [XWHAOFFreqPuretoneInputItemModel] = []
        var dashedMidItems: [XWHAOFFreqPuretoneInputItemModel] = []
        var dashedHighItems: [XWHAOFFreqPuretoneInputItemModel] = []
        var dashedMpoItems: [XWHAOFFreqPuretoneInputItemModel] = []
        var solidLowItems: [XWHAOFFreqPuretoneInputItemModel] = []
        var solidMidItems: [XWHAOFFreqPuretoneInputItemModel] = []
        var solidHighItems: [XWHAOFFreqPuretoneInputItemModel] = []
        var solidMpoItems: [XWHAOFFreqPuretoneInputItemModel] = []
        if isLeft {
            lineColor = UIColor(hex: 0x007EFF)!
            
            chartTipIconName = "left_ear_chart_tip_icon"
            
            markerBg = R.image.left_chart_wdrc_marker_bg()
            
            dashedLowItems = wdrcContainerModel.left?.dashedLow.items ?? []
            dashedMidItems = wdrcContainerModel.left?.dashedMid.items ?? []
            dashedHighItems = wdrcContainerModel.left?.dashedHigh.items ?? []
            dashedMpoItems = wdrcContainerModel.left?.dashedMpo.items ?? []
            solidLowItems = wdrcContainerModel.left?.solidLow.items ?? []
            solidMidItems = wdrcContainerModel.left?.solidMid.items ?? []
            solidHighItems = wdrcContainerModel.left?.solidHigh.items ?? []
            solidMpoItems = wdrcContainerModel.left?.solidMpo.items ?? []
        } else {
            lineColor = UIColor(hex: 0xFF5D34)!
            
            chartTipIconName = "right_ear_chart_tip_icon"
            
            markerBg = R.image.right_chart_wdrc_marker_bg()
        
            dashedLowItems = wdrcContainerModel.right?.dashedLow.items ?? []
            dashedMidItems = wdrcContainerModel.right?.dashedMid.items ?? []
            dashedHighItems = wdrcContainerModel.right?.dashedHigh.items ?? []
            dashedMpoItems = wdrcContainerModel.right?.dashedMpo.items ?? []
            solidLowItems = wdrcContainerModel.right?.solidLow.items ?? []
            solidMidItems = wdrcContainerModel.right?.solidMid.items ?? []
            solidHighItems = wdrcContainerModel.right?.solidHigh.items ?? []
            solidMpoItems = wdrcContainerModel.right?.solidMpo.items ?? []
        }
        
        let lang = AppFunctionHelper.getLocalPrimaryLanguage()
        if lang != "zh" {
            chartTipIconName += "_en"
        }
        
        iconView.image = UIImage(named: chartTipIconName)

        markerView.image = markerBg
        
        var dataSets: [LineChartDataSet] = []
        /*
        let dashedLowDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: dashedLowItems)
        let dashedMidDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: dashedMidItems)
        let dashedHighDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: dashedHighItems)
        let dashedMpoDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: dashedMpoItems)
        let solidLowDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: solidLowItems)
        let solidMidDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: solidMidItems)
        let solidHighDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: solidHighItems)
        let solidMpoDataEntries: [ChartDataEntry] = getChartDataEntryList(inputItems: solidMpoItems)
         */
        
        let highlightLineHeight: CGFloat = 3
        
        var lineWidthLow: CGFloat = 1
        var lineWidthMid: CGFloat = 1
        var lineWidthHigh: CGFloat = 1
        var lineWidthMpo: CGFloat = 1
        
        var singleSheetOperationModel: XWHAOFWDRCGainSingleSheetOperationModel
        if isLeft {
            singleSheetOperationModel = sheetOperationModel.leftOperation
        } else {
            singleSheetOperationModel = sheetOperationModel.rightOperation
        }
        
        var isContain = false
        
        isContain = singleSheetOperationModel.mpoItemList.contains(where: { $0.isSelected })
        if isContain {
            lineWidthMpo = highlightLineHeight
        }
        
        isContain = singleSheetOperationModel.loudItemList.contains(where: { $0.isSelected })
        if isContain {
            lineWidthHigh  = highlightLineHeight
        }
        
        isContain = singleSheetOperationModel.midvoiceItemList.contains(where: { $0.isSelected })
        if isContain {
            lineWidthMid  = highlightLineHeight
        }
        
        isContain = singleSheetOperationModel.whisperItemList.contains(where: { $0.isSelected })
        if isContain {
            lineWidthLow  = highlightLineHeight
        }
        
        if operationModel.isShowRealEarGain {
            let isDashLine = false
            
            let lowDataSet = getChartDataSet(inputItems: solidLowItems, lineColor: lineColor, isDashLine: isDashLine, label: solidLowDateSetLabel, lineWidth: lineWidthLow)
            let midDataSet = getChartDataSet(inputItems: solidMidItems, lineColor: lineColor, isDashLine: isDashLine, label: solidMidDateSetLabel, lineWidth: lineWidthMid)
            let highDataSet = getChartDataSet(inputItems: solidHighItems, lineColor: lineColor, isDashLine: isDashLine, label: solidHighDateSetLabel, lineWidth: lineWidthHigh)
            
            dataSets.append(lowDataSet)
            dataSets.append(midDataSet)
            dataSets.append(highDataSet)
        }
        
        if operationModel.isShowTargetGain {
            let isDashLine = true
            
            let lowDataSet = getChartDataSet(inputItems: dashedLowItems, lineColor: lineColor, isDashLine: isDashLine, label: dashedLowDateSetLabel, lineWidth: 1)
            let midDataSet = getChartDataSet(inputItems: dashedMidItems, lineColor: lineColor, isDashLine: isDashLine, label: dashedMidDateSetLabel, lineWidth: 1)
            let highDataSet = getChartDataSet(inputItems: dashedHighItems, lineColor: lineColor, isDashLine: isDashLine, label: dashedHighDateSetLabel, lineWidth: 1)
            
            dataSets.append(lowDataSet)
            dataSets.append(midDataSet)
            dataSets.append(highDataSet)
        }
        
        if operationModel.isShowMaxMPO {
            let isDashLine = true
            let tLineColor = majorTextColor
            
            let mpoDataSet = getChartDataSet(inputItems: dashedMpoItems, lineColor: tLineColor, isDashLine: isDashLine, label: maxMPODateSetLabel, lineWidth: 1)
            
            dataSets.append(mpoDataSet)
        }
        
        if operationModel.isShowRealMPO {
            let isDashLine = false
            let tLineColor = majorTextColor
            
            let mpoDataSet = getChartDataSet(inputItems: solidMpoItems, lineColor: tLineColor, isDashLine: isDashLine, label: realMPODateSetLabel, lineWidth: lineWidthMpo)
            
            dataSets.append(mpoDataSet)
        }
        
        //目前折线图只包括1根折线
        let chartData = LineChartData(dataSets: dataSets)
        
        //设置折现图数据
        chartView.data = chartData
    }
    
    private func getChartDataSet(inputItems: [XWHAOFFreqPuretoneInputItemModel], lineColor: UIColor, isDashLine: Bool, label: String, lineWidth: CGFloat) -> LineChartDataSet {
        let entryList = getChartDataEntryList(inputItems: inputItems)
        let dataSet = getChartDataSet(inputEntryList: entryList, lineColor: lineColor, isDashLine: isDashLine, label: label, lineWidth: lineWidth)
        
        return dataSet
    }
    
    private func getChartDataEntryList(inputItems: [XWHAOFFreqPuretoneInputItemModel]) -> [ChartDataEntry] {
        var retList: [ChartDataEntry] = []
        for (_, iItem) in inputItems.enumerated() {
            if let tIndex = freqBandList.firstIndex(where: { $0 == iItem.freqBand }) {
                let entry = ChartDataEntry.init(x: Double(tIndex), y: iItem.value)
                retList.append(entry)
            }
        }
        
        return retList
    }
    
    private func getChartDataSet(inputEntryList: [ChartDataEntry], lineColor: UIColor, isDashLine: Bool, label: String, lineWidth: CGFloat) -> LineChartDataSet {
        let dataSet = LineChartDataSet(entries: inputEntryList, label: label)
        config(chartDataSet: dataSet, lineColor: lineColor, isDashLine: isDashLine, lineWidth: lineWidth)
        return dataSet
    }
    
    private func config(chartDataSet: LineChartDataSet, lineColor: UIColor, isDashLine: Bool, lineWidth: CGFloat) {
        //        chartDataSet.highlightEnabled = false
        chartDataSet.drawVerticalHighlightIndicatorEnabled = false
        chartDataSet.drawHorizontalHighlightIndicatorEnabled = false
        chartDataSet.drawValuesEnabled = false
        chartDataSet.drawCirclesEnabled = false
        chartDataSet.drawCircleHoleEnabled = false
        chartDataSet.mode = .linear
        chartDataSet.lineWidth = lineWidth
        chartDataSet.setColor(lineColor)
        if isDashLine {
            chartDataSet.lineDashLengths = [2, 2]
        } else {
            chartDataSet.lineDashLengths = nil
        }
        
        //开启填充色绘制
        chartDataSet.drawFilledEnabled = false
//        let gradientColors = [lineColor.cgColor, UIColor.white.cgColor] as CFArray
//        //每组颜色所在位置（范围0~1)
//        let colorLocations:[CGFloat] = [1.0, 0.0]
//        //生成渐变色
//        if let gradient = CGGradient.init(colorsSpace: CGColorSpaceCreateDeviceRGB(),
//                                          colors: gradientColors, locations: colorLocations) {
//            //将渐变色作为填充对象s
//            chartDataSet.fill = Fill.fillWithLinearGradient(gradient, angle: 90)
//            chartDataSet.fillFormatter = DefaultFillFormatter(block: { dataSet, dataProvider in
//                CGFloat(self.chartView.leftAxis.axisMaximum)
//            })
//        }
    }

}

extension XWHAOFFittingWDRCGainLineChartView {
    
    override func configXAxis() {
        chartView.maxVisibleCount = 1000
        
        chartView.xAxis.labelPosition = .bottom
        
        let xMaxValue = freqBandList.count - 1
        chartView.xAxis.axisMaxLabels = xMaxValue + 1
        
        chartView.xAxis.axisMinimum = 0
        chartView.xAxis.granularity = 1
        chartView.xAxis.axisMaximum = Double(xMaxValue)
        
        chartView.xAxis.labelCount = chartView.xAxis.axisMaxLabels
        chartView.xAxis.forceLabelsEnabled = true
//        chartView.xAxis.granularityEnabled = true
        
        chartView.xAxis.axisLineWidth = 1
        chartView.xAxis.axisLineColor = UIColor.black.withAlphaComponent(0.05)
        chartView.xAxis.drawAxisLineEnabled = true
        
        chartView.xAxis.gridLineWidth = 1
        chartView.xAxis.gridColor = UIColor.black.withAlphaComponent(0.05)
        chartView.xAxis.drawGridLinesEnabled = true
        
        chartView.xAxis.labelFont = AppFont.harmonyOSSans(ofSize: 10)
        chartView.xAxis.labelTextColor = minorTextColor
        chartView.xAxis.valueFormatter = DefaultAxisValueFormatter(block: { [weak self] value, _ in
            let x = value.int
            var ret = x.string
            guard let self = self else {
                return ret
            }
            
            ret = self.getXValue(xIndex: x)
            
            return ret
        })
    }
    
    func getXValue(xIndex: Int) -> String {
        var ret = xIndex.string
        if xIndex < self.freqBandList.count, xIndex >= 0 {
            let tBand = self.freqBandList[xIndex]
            ret = AppFunctionHelper.getShortFreqBandText(freqBand: tBand)
        }
        
        return ret
    }
    
    override func configYAxis() {
        //        chartView.leftAxis.enabled = false
        
        let axisMinimum: Double = WDRCModule.wdrcChartMinValue
        let axisMaximum: Double = WDRCModule.wdrcChartMaxValue
        let labelCount = (axisMaximum.int - (axisMinimum.int)) / 10 + 1
        let granularity: Double = 10
        let isInverted = false
        chartView.leftAxis.inverted = isInverted
        chartView.leftAxis.axisMinimum = axisMinimum
        chartView.leftAxis.axisMaximum = axisMaximum
        chartView.leftAxis.granularity = granularity
        chartView.leftAxis.setLabelCount(labelCount, force: true)
        
        chartView.rightAxis.inverted = isInverted
        chartView.rightAxis.axisMinimum = axisMinimum
        chartView.rightAxis.axisMaximum = axisMaximum
        chartView.rightAxis.granularity = granularity
        chartView.rightAxis.setLabelCount(labelCount, force: true)
        
        let lineColor = UIColor.black.withAlphaComponent(0.05)
        let lineWidth = 0.5
        chartView.leftAxis.axisLineColor = lineColor
        chartView.leftAxis.axisLineWidth = lineWidth
        
        chartView.rightAxis.axisLineColor = lineColor
        chartView.rightAxis.axisLineWidth = lineWidth
        
        chartView.leftAxis.drawGridLinesEnabled = true
        chartView.leftAxis.drawLabelsEnabled = true
        
        chartView.rightAxis.drawGridLinesEnabled = false
        chartView.rightAxis.drawLabelsEnabled = false
        
        chartView.leftAxis.axisLineColor = lineColor
        chartView.leftAxis.axisLineWidth = lineWidth
        
        chartView.leftAxis.gridLineWidth = lineWidth
        chartView.leftAxis.gridColor = lineColor
        
        chartView.rightAxis.gridLineWidth = lineWidth
        chartView.rightAxis.gridColor = lineColor
        
        chartView.leftAxis.labelFont = AppFont.harmonyOSSans(ofSize: 10)
        chartView.leftAxis.labelTextColor = minorTextColor
        
        chartView.rightAxis.labelFont = AppFont.harmonyOSSans(ofSize: 10)
        chartView.rightAxis.labelTextColor = minorTextColor
        
        chartView.leftAxis.valueFormatter = DefaultAxisValueFormatter(block: { [weak self] value, _ in
//            let y = value.int / 10
            var ret = ""
            guard let _ = self else {
                return ret
            }
            
//            if y % 2 == 0 {
//                ret = value.int.string
//            } else {
//                ret = ""
//            }
            ret = value.int.string
            
            return ret
        })
    }
    
}

// MARK: - ChartViewDelegate
extension XWHAOFFittingWDRCGainLineChartView {
    
    override func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
        guard let dateSet = chartView.data?.dataSets[highlight.dataSetIndex] as? LineChartDataSet else { return }
        
        //        markerView.setShowOffset(chartView, entry: entry, highlight: highlight)
        ////        let entryIndex = dataSet.entryIndex(entry: entry)
        //        markerView.textLb.text =  .string
        //        markerView.detailLb.text = entry.y.int.string
        
        chartView.data?.dataSets.forEach({ set in
            guard let lineSet = set as? LineChartDataSet else {
                return
            }
            lineSet.entries.forEach({ $0.icon = nil })
        })
        if let dataEntry = dateSet.entries.first(where: { $0.x == highlight.x }) {
            if isLeft {
                dataEntry.icon = R.image.ac_no_mask_l_icon()
            } else {
                dataEntry.icon = R.image.ac_no_mask_r_icon()
            }
            chartView.data?.notifyDataChanged()
            chartView.notifyDataSetChanged()
        }
        
        let x = entry.x.int
        let y = entry.y.int
        
        var valueString = ""
        var titleString = ""
        let lowTitle = "（低声）"
        let midTitle = "（中声）"
        let highTitle = "（大声）"
        if dateSet.label == maxMPODateSetLabel {
            valueString = "MPO："
            titleString = "最大MPO"
        } else if dateSet.label == realMPODateSetLabel {
            valueString = "MPO："
            titleString = "设备MPO"
        } else if dateSet.label == dashedLowDateSetLabel {
            valueString = "目标增益："
            let tValue = WDRCModule.getWDRCHighMidLowDB(deviceType: self.deviceType, highMidLow: 2)
            titleString = "\(tValue)dB\(lowTitle)"
        } else if dateSet.label == dashedMidDateSetLabel {
            valueString = "目标增益："
            let tValue = WDRCModule.getWDRCHighMidLowDB(deviceType: self.deviceType, highMidLow: 1)
            titleString = "\(tValue)dB\(midTitle)"
        } else if dateSet.label == dashedHighDateSetLabel {
            valueString = "目标增益："
            let tValue = WDRCModule.getWDRCHighMidLowDB(deviceType: self.deviceType, highMidLow: 0)
            titleString = "\(tValue)dB\(highTitle)"
        } else if dateSet.label == solidLowDateSetLabel {
            valueString = "插入增益："
            let tValue = WDRCModule.getWDRCHighMidLowDB(deviceType: self.deviceType, highMidLow: 2)
            titleString = "\(tValue)dB\(lowTitle)"
        } else if dateSet.label == solidMidDateSetLabel {
            valueString = "插入增益："
            let tValue = WDRCModule.getWDRCHighMidLowDB(deviceType: self.deviceType, highMidLow: 1)
            titleString = "\(tValue)dB\(midTitle)"
        } else if dateSet.label == solidHighDateSetLabel {
            valueString = "插入增益："
            let tValue = WDRCModule.getWDRCHighMidLowDB(deviceType: self.deviceType, highMidLow: 0)
            titleString = "\(tValue)dB\(highTitle)"
        }
        
        let ret = getXValue(xIndex: x)
        
        let retString = "\(titleString)/n频段：\(ret)Hz/n\(valueString)\(y.string)\(volumeUnitText)"
        markerView.setLabel(retString)
    }
    
    func chartValueNothingSelected(_ chartView: ChartViewBase) {
        chartView.data?.dataSets.forEach({ set in
            guard let lineSet = set as? LineChartDataSet else {
                return
            }
            lineSet.entries.forEach({ $0.icon = nil })
        })
        
        chartView.data?.notifyDataChanged()
        chartView.notifyDataSetChanged()
    }
    
}
